package com.im.tcp.handler;

import com.im.tcp.utils.SessionSocketHolder;
import com.lld.im.common.constants.Constants;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import io.netty.util.AttributeKey;
import lombok.extern.slf4j.Slf4j;

/**
 * 心跳检测 也就是基于Netty的事件驱动 在指定时间内客户端未发起读写操作 就触发一个读写空闲事件
 *      可以在客户端的每次操作时记录时间 在每一次事件触发时 校验是否超过设定超时时间 然后选择断开channel或者删除redis缓存
 */
@Slf4j
public class HeartCheckHandler extends ChannelInboundHandlerAdapter {


    private int idleTime;

    public HeartCheckHandler(int idleTime) {
        this.idleTime = idleTime;
    }

    /**
     * 当用户的读写操作超过指定时间 会触发这个时间
     *
     * @param ctx
     * @param evt
     * @throws Exception
     */
    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        IdleStateEvent stateEvent = (IdleStateEvent) evt;
        if (stateEvent.state() == IdleState.READER_IDLE) {
            log.info("读空闲");
        } else if (stateEvent.state() == IdleState.WRITER_IDLE) {
            log.info("写空闲");
        } else if (stateEvent.state() == IdleState.ALL_IDLE) {
            //TODO 判断是否超时 nowTime-lastReadTime>idleTime
            Long lastTime = (Long) ctx.channel().attr(AttributeKey.valueOf(Constants.PING_LAST_TIME)).get();
            long nowTime = System.currentTimeMillis();
            if(lastTime!=null&&(nowTime-lastTime)>idleTime){
                //TODO 用户超时未响应 修改用户状态为离线
                SessionSocketHolder.offlineUserSession(ctx.channel());
            }
        }
    }


}
